package main

import "fmt"

// 没使用泛型 只能判断字符串是否相等
//func same(a, b string) bool { return a == b }

func same[T int | string | float64](a, b T) bool {
	return a == b
}

// 泛型结构体
type Persion[T any] struct {
	Name string
	Sex  T
}

// 泛型map  go自带的类型 any comparable一切可以比较的东西
type Tmap[K comparable, V string | int] map[K]V

// 泛型切片
type TSlice[T any] []T

// 定义自己的泛型约束
type MyType interface {
	int | float64 | string | int32 | int64
}

func Test[T MyType](s T) {
	fmt.Println(s)
}

// ~ 泛型模糊匹配
type My1Type interface {
	~int | ~string
}

type My1Int int

func Test1[T My1Type](s T) {
	fmt.Println(s)
}

// 泛型约束接口
type My2Type interface {
	Get()
}

type MyT struct {
}

func (m *MyT) Get() {
	fmt.Println("Get")
}

func Test2[T My2Type](s T) {
	fmt.Println(s)
}

// 泛型结构体 泛型方法 限制传递的类型必须为接口定义的类型
type MyStruct interface {
	~int | ~int64
}

type MS[T MyStruct] struct {
	Name T
}

func (m *MS[T]) Get(t T) {
	fmt.Println(t, m.Name)
}

func main() {
	fmt.Println("********** 泛型函数 *************")
	fmt.Println(same("1", "2"))
	// fmt.Println(same(1, 2)) // 如果不加泛型 没法比较 类型写成了string
	fmt.Println(same(1.2, 2.3))

	fmt.Println("********** 泛型结构体 **************")
	p := Persion[int]{}
	p.Name = "张三"
	p.Sex = 18

	p1 := Persion[string]{}
	p1.Name = "张三"
	p1.Sex = "18岁"

	fmt.Println("********** 泛型map **************")
	m := Tmap[int, string]{}
	m[1] = "1"

	m1 := Tmap[string, int]{}
	m1["1"] = 1

	fmt.Println("********** 泛型切片 **************")
	s := make(TSlice[string], 6)
	s[4] = "1"

	fmt.Println("********** 自定义泛型约束 **************")
	Test(123)
	Test("123")

	fmt.Println("********** 自定义泛型约束 ~模糊匹配 **************")
	var my1 My1Int = 222
	Test1(My1Int(123))
	Test1(my1)

	fmt.Println("********** 自定义泛型约束 接口函数约束 **************")
	m2 := MyT{}
	Test2(&m2)

	fmt.Println("********** 泛型结构体 泛型方法 限制结构体方法必须为接口定义的类型 **************")
	m3 := MS[int]{}
	m3.Name = 222
	m3.Get(123)
}
